/**
 * 
 */
package com.goktech.commons.field;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.regex.Pattern;

import com.goktech.commons.utils.StringUtils;

/**
 * @author 24252
 * 参数字段校验的工具类
 */
public class ValidationUitls {

	public static void validation(String paranName,String TypeName,Object paramValue,Colum colum){
		if(TypeName.equals(String.class.getTypeName()) || paramValue instanceof String){
			validationString(paranName,(String)paramValue,colum);
		}else if(TypeName.equals(Integer.class.getTypeName()) || paramValue instanceof Integer){
			validationInteger(paranName,(Integer)paramValue,colum);
		}else if(TypeName.equals(Double.class.getTypeName()) || paramValue instanceof Double){
			validationDouble(paranName,(Double)paramValue, colum);
		}else if(TypeName.equals(Float.class.getTypeName()) || paramValue instanceof Float){
			validationFloat(paranName, (Float)paramValue, colum);
		}else if(TypeName.equals(Character.class.getTypeName()) || paramValue instanceof Character){
			validationCharacter(paranName, (Character)paramValue, colum);
		}else if(TypeName.equals(Short.class.getTypeName()) || paramValue instanceof Short){
			validationSort(paranName, (Short)paramValue, colum);
		}else if(TypeName.equals(Long.class.getTypeName()) || paramValue instanceof Long){
			validationLong(paranName, (Long)paramValue, colum);
		}else if(paramValue instanceof Collection<?>){
			validationCollection(paranName, (Collection<?>)paramValue, colum);
		}
	}
	
	public static void validationString(String paranName,String paramValue,Colum colum){
		if(colum.NotEmpty() && StringUtils.isEmpty(paramValue)){
			throwException(String.format("%s must not null", paranName), colum);
		}
		
		if(paramValue != null && paramValue.length() > colum.maxLength()){
			throwException(String.format("The length of %s cannot be greater than %d",paranName,colum.maxLength()), colum);
		}
		 
		if(colum.regex().length > 0){
			validationRegex(paranName, paramValue, colum);
		}
	}
	
	public static void validationInteger(String paranName,Integer paramValue,Colum colum){
		if(colum.NotNull() && paramValue == null){
			throwException(String.format("%s must not null", paranName), colum);
		}
		if(paramValue != null && (paramValue > colum.max() && paramValue < colum.min())){
			throwException(String.format("The value of this %s cannot be greater than %d is less than %d",paranName,colum.max(),colum.min()), colum);
		}
	}
	
	public static void validationDouble(String paranName,Double paramValue,Colum colum){
		if(colum.NotNull() && paramValue == null){
			throwException(String.format("%s must not null", paranName),colum);
		}
		if(paramValue != null && (paramValue < colum.minDouble() || paramValue > colum.maxDouble())){
			throwException(String.format("The value of this %s cannot be greater than %f is less than %f",paranName,colum.maxDouble(),colum.minDouble()), colum);
		}
	}
	
	@Deprecated
	public static void validationFloat(String paranName,Float paramValue,Colum colum){
		
	}
	
	public static void validationRegex(String paranName,String paramValue,Colum colum){
		for(String pattern : colum.regex()){
            if(!Pattern.matches(pattern, paramValue)){
            	throwException(String.format("This %s has a value format error",paranName),colum);
            }
        }
	}
	
	public static void validationSort(String paranName,Short paramValue,Colum colum){
		if(colum.NotNull() && paramValue == null){
			throwException(String.format("%s must not null", paranName),colum);
		}
		if(paramValue != null && (paramValue < colum.minShort() || paramValue > colum.maxShort())){
			throwException(String.format("The value of this %s cannot be greater than %d is less than %d",paranName,colum.maxShort(),colum.minShort()), colum);
		}
	}
	
	@Deprecated
	public static void validationCharacter(String paranName,Character paramValue,Colum colum){
	
	}
	
	
	public static void validationLong(String paranName,Long paramValue,Colum colum){
		if(colum.NotNull() && paramValue == null){
			throwException(String.format("%s must not null", paranName),colum);
		}
		if(paramValue != null && (paramValue < colum.minLong() || paramValue > colum.maxLong())){
			throwException(String.format("The value of this %s cannot be greater than %d is less than %d",paranName,colum.maxLong(),colum.minLong()), colum);
		}
	}
	
	public static void validationCollection(String paranName,Collection<?> paramValue,Colum colum){
		if(colum.NotNull() && paramValue == null){
			throwException(String.format("%s must not null", paranName),colum);
		}
		if(paramValue != null && paramValue.size() < colum.minLength()){
			throwException(String.format("The length of %s cannot be greater than %d",paranName,colum.maxLength()),colum);
		}
	}
	
	private static void throwException(String message,Colum colum){
		throw new ValiadationException(StringUtils.isEmpty(colum.message()) ? message : colum.message());
	}
	
	//扫描带有变量
	public static void ScanField(Object instance,Class<?> clazz){
		Field[] fields  = clazz.getDeclaredFields();
		while(fields != null && fields.length > 0){
			for(Field field: fields){
				Colum obj = field.getAnnotation(Colum.class);
				if(obj != null){
					validation(field.getName(),field.getType().getName(), getValue(instance,clazz, field.getName()), obj);
				}
			}
			fields = clazz.getSuperclass().getDeclaredFields();
			clazz = clazz.getSuperclass();
		}
	}
	
	private static Object getValue(Object instance,Class<?> clazz,String fieldName){
		try {
			Object result = clazz.getMethod(getGetter(fieldName)).invoke(instance);
			return result;
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 得到一个方法签名
	 * @param fieldName
	 * @return
	 */
	private static String getGetter(String fieldName){
		return "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
	}
}
